﻿#region File and License Information
/*
<File>
	<License>
		Copyright © 2009 - 2017, Daniel Vaughan. All rights reserved.
		This file is part of Calcium (http://calciumsdk.net), 
		which is released under the MIT License.
		See file /Documentation/License.txt for details.
	</License>
	<CreationDate>2009-04-25 14:43:57Z</CreationDate>
</File>
*/
#endregion

using System;

using Outcoder.Services.MessageService;

namespace Outcoder.Services.Implementation
{
	/// <summary>
	/// Base implementation of <see cref="IMessageService"/>.
	/// </summary>
	public abstract class MessageServiceBase : IMessageService
	{
		public Func<string> DefaultMessageCaptionFunc { get; set; }
		public Func<string> DefaultQuestionCaptionFunc { get; set; }
		public Func<string> DefaultWarningCaptionFunc { get; set; }
		public Func<string> DefaultErrorCaptionFunc { get; set; }

		/*TODO: implement a means to modify the user MessageImportance threshold value. 
		 * This be done by subscribing to a composite property changed event. */
		public static MessageImportance MinumumImportance { get; protected set; }

		static MessageServiceBase()
		{
			MinumumImportance = MessageImportance.Low;
		}

		/// <summary>
		/// Shows a custom dialogue. Override this message in test mocks.
		/// This is the only place where a MessageBox is shown.
		/// </summary>
		/// <param name="message">The message text to display.</param>
		/// <param name="details">Can be <code>null</code>. 
		/// A detailed message that is display in a hidden area of the dialog, 
		/// and revealed on user request.</param>
		/// <param name="caption">The caption to display at the top of the dialog.</param>
		/// <param name="messageButton">The message box button enum value, 
		/// which determines what buttons are shown.</param>
		/// <param name="messageImage">The message box image, 
		/// which determines what icon is used.</param>
		/// <param name="importanceThreshold">The minimum filter level 
		/// that a user must have in order to receive the message.</param>
		/// <returns>The result of showing the message box.</returns>
		public abstract MessageResult ShowCustomDialog(string message, string caption,
														  MessageButton messageButton, MessageImage messageImage,
														  MessageImportance? importanceThreshold, string details);

		#region Messages

		string GetDefaultMessageCaption()
		{
			string defaultCaption = DefaultMessageCaptionFunc != null
										? DefaultMessageCaptionFunc() : "Message";
			return defaultCaption;
		}
//		public void ShowMessage(string message, MessageImportance importanceThreshold)
//		{
//			ShowMessage(message, null, importanceThreshold);
//		}

//		public void ShowMessage(string message, string caption = null, MessageImportance importanceThreshold = MessageImportance.High)
//		{
//			ShowMessage(message, caption, importanceThreshold, null);
//		}

		public void ShowMessage(
			string message, 
			string caption = null,
			MessageImportance importanceThreshold = MessageImportance.High, 
			string details = null)
		{
			ShowCustomDialog(message, caption ?? GetDefaultMessageCaption(), 
				MessageButton.OK, MessageImage.Information, importanceThreshold, details);
		}
		#endregion

		#region Warnings
		string GetDefaultWarningCaption()
		{
			string defaultCaption = DefaultWarningCaptionFunc != null
										? DefaultWarningCaptionFunc() : "Warning";
			return defaultCaption;
		}

		public void ShowWarning(string message, string caption = null, string details = null)
		{
			ShowCustomDialog(message, caption ?? GetDefaultWarningCaption(),
				MessageButton.OK, MessageImage.Warning, null, details);
		}
		#endregion

		#region Errors
		string GetDefaultErrorCaption()
		{
			string defaultCaption = DefaultErrorCaptionFunc != null
										? DefaultErrorCaptionFunc() : "Error";
			return defaultCaption;
		}

		public void ShowError(string message, string caption = null, string details = null)
		{
			ShowCustomDialog(message, caption ?? GetDefaultErrorCaption(), 
				MessageButton.OK, MessageImage.Error, null, details);
		}
		#endregion

		#region Questions

		string GetDefaultQuestionCaption()
		{
			string defaultCaption = DefaultQuestionCaptionFunc != null 
										? DefaultQuestionCaptionFunc() : "Question";
			return defaultCaption;
		}

		public bool AskYesNoQuestion(string question, string caption = null, string details = null)
		{
			var messageBoxResult = ShowCustomDialog(question, caption ?? GetDefaultQuestionCaption(), 
				MessageButton.YesNo, MessageImage.Question, null, null);
			return messageBoxResult == MessageResult.Yes 
				|| messageBoxResult == MessageResult.OK;
		}

		public bool AskOkCancelQuestion(string question, string caption = null, string details = null)
		{
			var messageBoxResult = ShowCustomDialog(question, caption ?? GetDefaultQuestionCaption(), 
				MessageButton.OKCancel, MessageImage.Question, null, null);
			return messageBoxResult == MessageResult.OK 
				|| messageBoxResult == MessageResult.Yes;
		}
		
#if SILVERLIGHT || MONODROID || MONOTOUCH
		public abstract void AskQuestion<TResponse>(
			IQuestion<TResponse> question, 
			Action<QuestionResult<TResponse>> resultHandler) 
				where TResponse : class, IQuestionResult;

//		public abstract void AskQuestionWithTextResponse(
//			TextResponseQuestion textResponseQuestion,
//			Action<QuestionResult<TextResponse>> resultHandler);
#if WINDOWS_PHONE
		public abstract System.Threading.Tasks.Task<QuestionResult<TResponse>> AskQuestionAsync<TResponse>(
			IQuestion<TResponse> question);
#endif
#else
		public abstract TextResponse AskQuestionWithTextResponse(TextResponseQuestion textResponseQuestion);
#endif

		public YesNoCancelQuestionResult AskYesNoCancelQuestion(string question, string caption = null, string details = null)
		{
			var dialogResult = ShowCustomDialog(question, caption ?? GetDefaultQuestionCaption(),
				MessageButton.YesNoCancel, MessageImage.Question, null, details);

			switch (dialogResult)
			{
				case MessageResult.Yes:
					return YesNoCancelQuestionResult.Yes;
				case MessageResult.No:
					return YesNoCancelQuestionResult.No;
				case MessageResult.Cancel:
					return YesNoCancelQuestionResult.Cancel;
				default:
					/* Should never get here. */
					throw new InvalidOperationException("Invalid dialog MessageBoxResult."); /* TODO: Make localizable resource. */
			}
		}

		#endregion
	}
}
